package com.qimu.saiyou.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qimu.saiyou.annotation.AuthCheck;
import com.qimu.saiyou.common.BaseResponse;
import com.qimu.saiyou.common.ErrorCode;
import com.qimu.saiyou.common.ResultUtils;
import com.qimu.saiyou.constant.UserConstant;
import com.qimu.saiyou.exception.BusinessException;
import com.qimu.saiyou.manager.RedisLimiterManager;
import com.qimu.saiyou.model.dto.productorder.ProductOrderQueryRequest;
import com.qimu.saiyou.model.entity.ProductInfo;
import com.qimu.saiyou.model.entity.ProductOrder;
import com.qimu.saiyou.model.entity.User;
import com.qimu.saiyou.service.ProductInfoService;
import com.qimu.saiyou.service.ProductOrderService;
import com.qimu.saiyou.service.UserService;
import com.qimu.saiyou.utils.RedissonLockUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 商品订单
 *
 *@author: FeiXiang
 * 
 */
@RestController
@RequestMapping("/product_order")
@Slf4j
public class ProductOrderController {
    @Resource
    private ProductOrderService productOrderService;
    @Resource
    private UserService userService;
    @Resource
    private RedisLimiterManager redisLimiterManager;
    @Resource
    private ProductInfoService productInfoService;
    @Resource
    private RedissonLockUtil redissonLockUtil;

    // region 增删改查

    @PostMapping("/list/vo")
    public BaseResponse<Page<ProductOrder>> listMyProductOrderByPage(@RequestBody ProductOrderQueryRequest productOrderQueryRequest, HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        int current = productOrderQueryRequest.getCurrent();
        int pageSize = productOrderQueryRequest.getPageSize();
        String sortField = productOrderQueryRequest.getSortField();
        String sortOrder = productOrderQueryRequest.getSortOrder();
        String searchText = productOrderQueryRequest.getSearchText();
        Integer status = productOrderQueryRequest.getStatus();
        LambdaQueryWrapper<ProductOrder> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(searchText)) {
            lambdaQueryWrapper.and(w -> w.eq(ProductOrder::getOrderName, searchText)
                    .or()
                    .eq(ProductOrder::getProductInfo, searchText));
        }
        lambdaQueryWrapper.eq(ObjectUtils.isNotEmpty(status), ProductOrder::getStatus, status);
        if (!userService.isAdmin(loginUser)) {
            lambdaQueryWrapper.eq(ProductOrder::getUserId, loginUser.getId());
        }
        Page<ProductOrder> productOrderPage = productOrderService.page(new Page<>(current, pageSize), lambdaQueryWrapper);
        List<ProductOrder> sortedList = productOrderPage.getRecords().stream()
                .sorted(Comparator.comparing(ProductOrder::getCreateTime)
                        .reversed())
                .sorted(Comparator.comparingInt(o -> o.getStatus() == 0 ? 0 : 1))
                .collect(Collectors.toList());
        productOrderPage.setRecords(sortedList);
        return ResultUtils.success(productOrderPage);
    }

    /**
     * 创建订单
     *
     * @param id      商品id
     * @param request 要求
     * @return {@link BaseResponse}<{@link Long}>
     */
    @PostMapping("/create")
    public BaseResponse<Long> createOrder(long id, HttpServletRequest request) {
        if (id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        ProductInfo productInfo = productInfoService.getById(id);
        if (productInfo == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        User loginUser = userService.getLoginUser(request);
        return redissonLockUtil.redissonDistributedLocks("saiyou:createOrder:" + loginUser.getId(), () -> {
            Long count = productOrderService.lambdaQuery()
                    .eq(ProductOrder::getUserId, loginUser.getId())
                    .eq(ProductOrder::getStatus, 0)
                    .count();
            if (count > 0) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "有相同订单未支付~");
            }
            ProductOrder productOrder = new ProductOrder();
            productOrder.setUserId(loginUser.getId());
            productOrder.setProductId(productInfo.getId());
            productOrder.setOrderName(productInfo.getName());
            productOrder.setTotal(productInfo.getTotal());
            productOrder.setStatus(0);
            productOrder.setProductInfo(productInfo.getDescription());
            productOrderService.save(productOrder);
            return ResultUtils.success(productOrder.getId());
        });
    }

    @PostMapping("/cancel")
    public BaseResponse<Boolean> cancelOrder(long id, HttpServletRequest request) {
        if (id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User loginUser = userService.getLoginUser(request);
        return redissonLockUtil.redissonDistributedLocks("saiyou:cancelOrder:" + loginUser.getId(), () -> {
            ProductOrder productOrder = productOrderService.getById(id);
            if (productOrder == null) {
                throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
            }
            if (productOrder.getStatus().equals(3) || productOrder.getStatus().equals(1) || productOrder.getStatus().equals(4)) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "当前订单不可取消");
            }
            if (!userService.isAdmin(loginUser) && !loginUser.getId().equals(productOrder.getUserId())) {
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
            }
            productOrder.setStatus(2);
            if (productOrder.getStatus().equals(1)) {
                Long userId = productOrder.getUserId();
                User user = userService.getById(userId);
                user.setUserCoin(user.getUserCoin() + productOrder.getTotal());
                userService.updateById(user);
            }
            return ResultUtils.success(productOrderService.updateById(productOrder));
        });
    }

    @PostMapping("/pay")
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse<Boolean> payOrder(long id, HttpServletRequest request) {
        if (id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User loginUser = userService.getLoginUser(request);
        return redissonLockUtil.redissonDistributedLocks("saiyou:pay:" + loginUser.getId(), () -> {
            ProductOrder productOrder = productOrderService.getById(id);
            if (productOrder == null) {
                throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
            }
            if (productOrder.getStatus().equals(3)) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "当前订单管理员已通过");
            }
            if (productOrder.getStatus().equals(1)) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "当前订单已支付");
            }
            if (productOrder.getStatus().equals(2)) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "当前订单已取消");
            }
            if (productOrder.getStatus().equals(4)) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "当前订单审核不通过");
            }
            if (loginUser.getUserCoin() - productOrder.getTotal() < 0) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "积分不足，快去做任务吧~");
            }
            loginUser.setUserCoin(loginUser.getUserCoin() - productOrder.getTotal());
            return ResultUtils.success(userService.updateById(loginUser));
        });
    }


    @PostMapping("/adopt")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Boolean> adoptOrder(long id) {
        if (id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        return redissonLockUtil.redissonDistributedLocks("saiyou:adoptOrder:" + id, () -> {
            ProductOrder productOrder = productOrderService.getById(id);
            if (productOrder == null) {
                throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
            }
            if (productOrder.getStatus() == 0) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "当前订单用户未支付");
            }
            if (productOrder.getStatus().equals(2)) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "当前订单已取消");
            }
            productOrder.setStatus(3);
            return ResultUtils.success(productOrderService.updateById(productOrder));
        });
    }

    @PostMapping("/refuse")
    @Transactional(rollbackFor = Exception.class)
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Boolean> refuseOrder(long id) {
        if (id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        return redissonLockUtil.redissonDistributedLocks("saiyou:refuseOrder:" + id, () -> {
            ProductOrder productOrder = productOrderService.getById(id);
            if (productOrder == null) {
                throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
            }
            if (productOrder.getStatus().equals(2)) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "当前订单已取消");
            }
            productOrder.setStatus(4);
            if (productOrder.getStatus().equals(1)) {
                Long userId = productOrder.getUserId();
                User user = userService.getById(userId);
                user.setUserCoin(user.getUserCoin() + productOrder.getTotal());
                userService.updateById(user);
            }
            return ResultUtils.success(productOrderService.updateById(productOrder));
        });
    }


    @PostMapping("/delete")
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse<Boolean> deleteOrder(long id,HttpServletRequest request) {
        if (id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        return redissonLockUtil.redissonDistributedLocks("saiyou:deleteOrder:" + id, () -> {
            ProductOrder productOrder = productOrderService.getById(id);
            if (productOrder == null) {
                throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
            }
            User loginUser = userService.getLoginUser(request);
            if (!userService.isAdmin(loginUser) && !loginUser.getId().equals(productOrder.getUserId())) {
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
            }
            if (productOrder.getStatus().equals(1)) {
                Long userId = productOrder.getUserId();
                User user = userService.getById(userId);
                user.setUserCoin(user.getUserCoin() + productOrder.getTotal());
                userService.updateById(user);
            }
            return ResultUtils.success(productOrderService.removeById(productOrder));
        });
    }
}
